package com.cskaoyan.javase.object._6clone.exercise;

/**
 * 深度克隆练习：请完成类FirstLevel的深度克隆。
 * 现在有三个类 FirstLevel 、SecondLevel 、ThirdLevel
 * FirstLevel 类有三个属性：
 * int firstIntValue;
 * double firstDoubleValue;
 * SecondLevel second;
 *
 * SecondLevel 类有三个属性：
 *
 * int secondIntValue;
 * double secondDoubleValue;
 * ThirdLevel third;
 *
 * ThirdLevel 类有两个属性：
 * int thirdIntValue;
 * double thirdDoubleValue;
 *
 * @since 17:39
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) throws CloneNotSupportedException {
        /*First first = new First(10, 20, new Second(100, 200, new Third(1000, 2000)));
        First cloneFirst = first.clone();

        first.second.third.thirdIntValue = 6666666;
        System.out.println(cloneFirst.second.third.thirdIntValue);*/

        First first = new First(10, 20, new Second(100, 200, new Third(1000, 2000, "张三")));
        First cloneFirst = first.clone();
        first.second.third.name = "李四";
        System.out.println(cloneFirst.second.third.name);
    }
}

class First implements Cloneable {
    int firstIntValue;
    double firstDoubleValue;
    Second second;

    public First(int firstIntValue, double firstDoubleValue, Second second) {
        this.firstIntValue = firstIntValue;
        this.firstDoubleValue = firstDoubleValue;
        this.second = second;
    }

    @Override
    protected First clone() throws CloneNotSupportedException {
        // 1.实现深度克隆,需要先做浅克隆
        First cloneFirst = (First) super.clone();
        // 2.将second引用指向的对象克隆一份
        Second cloneSecond = second.clone();
        // 3.将克隆first对象中的second引用指向克隆的Second对象
        cloneFirst.second = cloneSecond;
        return cloneFirst;
    }
}

class Second implements Cloneable {
    int secondIntValue;
    double secondDoubleValue;
    Third third;

    public Second(int secondIntValue, double secondDoubleValue, Third third) {
        this.secondIntValue = secondIntValue;
        this.secondDoubleValue = secondDoubleValue;
        this.third = third;
    }

    @Override
    protected Second clone() throws CloneNotSupportedException {
        Second cloneSecond = (Second) super.clone();
        // 需要克隆third指向的对象,需要克隆Third对象
        Third cloneThird = third.clone();
        cloneSecond.third = cloneThird;
        return cloneSecond;
    }
}

class Third implements Cloneable {
    int thirdIntValue;
    double thirdDoubleValue;

    /*
        String虽然是引用数据类型
        但是它无需深度克隆
        因为name引用指向的对象是不可变的
        一旦想要修改就会指向新的对象
        而原先的对象不会发生任何改变
     */
    String name;

    public Third(int thirdIntValue, double thirdDoubleValue) {
        this.thirdIntValue = thirdIntValue;
        this.thirdDoubleValue = thirdDoubleValue;
    }

    public Third(int thirdIntValue, double thirdDoubleValue, String name) {
        this.thirdIntValue = thirdIntValue;
        this.thirdDoubleValue = thirdDoubleValue;
        this.name = name;
    }

    @Override
    protected Third clone() throws CloneNotSupportedException {
        return (Third) super.clone();
    }
}